/***************************************************************
Copyright Statement:

This software/firmware and related documentation (EcoNet Software) 
are protected under relevant copyright laws. The information contained herein 
is confidential and proprietary to EcoNet (HK) Limited (EcoNet) and/or 
its licensors. Without the prior written permission of EcoNet and/or its licensors, 
any reproduction, modification, use or disclosure of EcoNet Software, and 
information contained herein, in whole or in part, shall be strictly prohibited.

EcoNet (HK) Limited  EcoNet. ALL RIGHTS RESERVED.

BY OPENING OR USING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY 
ACKNOWLEDGES AND AGREES THAT THE SOFTWARE/FIRMWARE AND ITS 
DOCUMENTATIONS (ECONET SOFTWARE) RECEIVED FROM ECONET 
AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON AN AS IS 
BASIS ONLY. ECONET EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, 
WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, 
OR NON-INFRINGEMENT. NOR DOES ECONET PROVIDE ANY WARRANTY 
WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTIES WHICH 
MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE ECONET SOFTWARE. 
RECEIVER AGREES TO LOOK ONLY TO SUCH THIRD PARTIES FOR ANY AND ALL 
WARRANTY CLAIMS RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES 
THAT IT IS RECEIVERS SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD 
PARTY ALL PROPER LICENSES CONTAINED IN ECONET SOFTWARE.

ECONET SHALL NOT BE RESPONSIBLE FOR ANY ECONET SOFTWARE RELEASES 
MADE TO RECEIVERS SPECIFICATION OR CONFORMING TO A PARTICULAR 
STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND 
ECONET'S ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE ECONET 
SOFTWARE RELEASED HEREUNDER SHALL BE, AT ECONET'S SOLE OPTION, TO 
REVISE OR REPLACE THE ECONET SOFTWARE AT ISSUE OR REFUND ANY SOFTWARE 
LICENSE FEES OR SERVICE CHARGES PAID BY RECEIVER TO ECONET FOR SUCH 
ECONET SOFTWARE.
***************************************************************/

#include <string.h>


#include "omci_adpt_common.h"
#include "omci_adpt_general.h"
#include "libgpon_flow.h"


static int omci_flow_handle_pptp_eth_uni(omci_me_info_ptr me_info);
static int omci_flow_handle_mbsp(omci_me_info_ptr me_info);
static int omci_flow_handle_mbpcd(omci_me_info_ptr me_info);
static int omci_flow_handle_vtfd(omci_me_info_ptr me_info);
static int omci_flow_handle_vtocd(omci_me_info_ptr me_info);
static int omci_flow_handle_802_1p_mapper(omci_me_info_ptr me_info);
static int omci_flow_handle_evtocd(omci_me_info_ptr me_info);
static int omci_flow_handle_gem_iw_tp(omci_me_info_ptr me_info);
static int omci_flow_handle_gem_ctp(omci_me_info_ptr me_info);
static int omci_flow_handle_veip(omci_me_info_ptr me_info);
static int omci_flow_handle_multi_gem_iw_tp(omci_me_info_ptr me_info);
static int omci_flow_handle_tcont(omci_me_info_ptr me_info);
static int omci_flow_handle_ts(omci_me_info_ptr me_info);
static int omci_flow_handle_td(omci_me_info_ptr me_info);
static int omci_flow_handle_pri_queue(omci_me_info_ptr me_info);


static uint16_t gpon_flow_me_index_map[OMCI_FLOW_MAX_MAP_NUM];
static gpon_flow_me_t gpon_flow_me_table[] = 
{
{0},/*index 0 for unsupported index, can not delete*/
/*Phase 1*/	
{OMCI_CLASS_ID_PPTP_ETHERNET_UNI,					omci_flow_handle_pptp_eth_uni},
{OMCI_CLASS_ID_MAC_BRIDGE_SERVICE_PROFILE,			omci_flow_handle_mbsp},
{OMCI_CLASS_ID_MAC_BRIDGE_PORT_CON_DATA,			omci_flow_handle_mbpcd},
{OMCI_CLASS_ID_VLAN_TAG_FILTER_DATA,				omci_flow_handle_vtfd},
{OMCI_CLASS_ID_802_1P_MAPPER,						omci_flow_handle_802_1p_mapper},
{OMCI_CLASS_ID_GEM_INTERWORK_TP, 					omci_flow_handle_gem_iw_tp},
{OMCI_CLASS_ID_GEM_PORT_CTP, 						omci_flow_handle_gem_ctp},

{OMCI_CLASS_ID_VIRTUAL_ETHERNET_INTERFACE_POINT, 	omci_flow_handle_veip},
{OMCI_CLASS_ID_MULTICAST_GEM_INTERWORK_TP, 			omci_flow_handle_multi_gem_iw_tp},
{OMCI_CLASS_ID_T_CONT, 								omci_flow_handle_tcont},
{OMCI_CLASS_ID_TRAFFIC_SCHEDULER, 					omci_flow_handle_ts},
{OMCI_CLASS_ID_TRAFFIC_DESCRIPTOR,					omci_flow_handle_td},
{OMCI_CLASS_ID_PRIORITY_QUEUE, 						omci_flow_handle_pri_queue},

/*Phase 2*/
{OMCI_CLASS_ID_VLAN_TAG_OPERATE,					omci_flow_handle_vtocd},
{OMCI_CLASS_ID_VLAN_TAG_EXTEND_OPERATE,				omci_flow_handle_evtocd},
};


void omci_flow_init_me_map(void)
{
    int i = 1;
    int omciMeTableSize = sizeof(gpon_flow_me_table)/sizeof(gpon_flow_me_t);
    if(omciMeTableSize > OMCI_FLOW_MAX_MAP_NUM)
    {
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR," Enter initStdOmciMap max=%d greater %d\n",
		omciMeTableSize, OMCI_FLOW_MAX_MAP_NUM);
        omciMeTableSize = OMCI_FLOW_MAX_MAP_NUM;
    }
    memset(&gpon_flow_me_index_map, 0, sizeof(gpon_flow_me_index_map));
    for(i = 1; i < omciMeTableSize; i++)
    {
        if(gpon_flow_me_table[i].class_id >= OMCI_FLOW_MAX_MAP_NUM)
        {
            omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"Enter initStdOmciMap classId=%d greater %d\n", 
				gpon_flow_me_table[i].class_id, OMCI_FLOW_MAX_MAP_NUM);
            continue;
        }
        gpon_flow_me_index_map[gpon_flow_me_table[i].class_id] = i;
    }    
}


static gpon_flow_me_t * omci_flow_get_me_by_classid(uint16_t classId)
{
    uint16_t me_index = 0;
    if( (classId >= 240 && classId <= 255) 
        || (classId >= 350 && classId <= 399)
        || (classId >= 65280 && classId <= 65535) 
        || classId >= OMCI_FLOW_MAX_MAP_NUM)
    {
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]unkown reserved ME(%d) .\n",__FUNCTION__,__LINE__, classId);
        return NULL;
    }

    me_index = gpon_flow_me_index_map[classId];
    omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%s][%d]: classId = %d, me_index = %d.\n",__FUNCTION__,__LINE__,classId, me_index);

    if(me_index == 0)
        return NULL;
    else
        return &gpon_flow_me_table[me_index];
}


/**
 * There is not much to do in this func, since driver only cares about PPTP
 * Eth UNI ME's instID which OLT happens to not be able to change.
 */
static int omci_flow_handle_pptp_eth_uni(omci_me_info_ptr me_info)
{  
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}

    if(MT_OMCI_MSG_TYPE_SET ==  me_info->msg_type){
        return 0;
    }else{
        return -1; // don't support any other actions
    }
    
    return -1;
}

/**
 * ret val: on success return 0
            on failure return -1
 */
static int omci_flow_handle_mbsp(omci_me_info_ptr me_info)
{
    meMbsp_raw_t mbspData = {0};
    FlowRawData_t ioctlData = {
        .classId = OMCI_CLASS_ID_MAC_BRIDGE_SERVICE_PROFILE,
        .data = &mbspData
    };
	omci_mac_br_service_ptr mac_br_srv_p = NULL;
        
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	mac_br_srv_p = (omci_mac_br_service_ptr)me_info->attributes;	
    if(mac_br_srv_p == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
    }
	ioctlData.msgType = me_info->msg_type;

	mbspData.instID	= me_info->inst_id;
	mbspData.uniBridgingEnable	= mac_br_srv_p->portBrInd;
	mbspData.helloTime			= mac_br_srv_p->helloTime;
	mbspData.dynFilterAgingTime = mac_br_srv_p->dynFilterAgeTime;

	if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type)
	{
        ioctlData.attrMask = ME_MBSP_ATTR_ALL;
    } 
	else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type)
	{
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
    } 
	else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type)
	{
        return -1;
    }    

    if ( 0 != gpon_flow_ioctl_import_me_data(&ioctlData) ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
        return -1;
    }
    
    return 0;
}


/**
 * ret val: on success return 0
            on failure return -1
 */
static int omci_flow_handle_mbpcd(omci_me_info_ptr me_info)
{
	meMbpcd_raw_t mbpcdData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_MAC_BRIDGE_PORT_CON_DATA,
		.data = &mbpcdData
	};
	omci_mac_br_port_cfg_ptr mb_port_cfg_data_p = NULL;
        
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	mb_port_cfg_data_p = (omci_mac_br_port_cfg_ptr)me_info->attributes;	
    if(mb_port_cfg_data_p == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
    }
	ioctlData.msgType = me_info->msg_type;

	mbpcdData.instID = me_info->inst_id;
	mbpcdData.bridgeID  = mb_port_cfg_data_p->bridgeIDPointer;
	mbpcdData.tpType    = mb_port_cfg_data_p->tpType;
	mbpcdData.tpPointer = mb_port_cfg_data_p->tpPointer;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type)
    {
        ioctlData.attrMask = ME_MBPCD_ATTR_ALL;
    }
    else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type)
    {
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
    }
    else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type)
    {
        return -1;
    }

    if ( 0 != gpon_flow_ioctl_import_me_data(&ioctlData) ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
        return -1;
    }

    return 0;
}

static int omci_flow_handle_vtocd(omci_me_info_ptr me_info)
{
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	if(MT_OMCI_MSG_TYPE_SET    == me_info->msg_type   || 
       MT_OMCI_MSG_TYPE_DELETE == me_info->msg_type   ||
       MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type) 
		return 0;
	else
		return -1;
}

static int omci_flow_handle_vtfd(omci_me_info_ptr me_info)
{
	meVtfd_raw_t vtfdData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_VLAN_TAG_FILTER_DATA,
		.data = &vtfdData
	};
	int i = 0;
    uint8_t * temp_ptr = NULL;
	omci_vlan_filter_ptr vlan_tag_filter_p = NULL;
        
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	vlan_tag_filter_p = (omci_vlan_filter_ptr)me_info->attributes;	
    if(vlan_tag_filter_p == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
    }
	ioctlData.msgType = me_info->msg_type;

	vtfdData.instID = me_info->inst_id;
    for(i = 0; i<MAX_GPON_VLAN_FILTER_LIST; i++){
        temp_ptr = vlan_tag_filter_p->VLANFilterList +(i<<1);
        vtfdData.vlanFilterList[i] = get16(temp_ptr);
    }
	vtfdData.forwardOperation= vlan_tag_filter_p->forwordOp;
	vtfdData.vlanFilterNums= vlan_tag_filter_p->entryNum;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_VTFD_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type)
		return -1;
    	
	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){ 
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	return 0;
}

static int omci_flow_handle_802_1p_mapper(omci_me_info_ptr me_info)
{
	me8021pMapper_raw_t mapperData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_802_1P_MAPPER,
		.data = &mapperData
	};
	omci_802_1p_map_service_ptr mapper_p = NULL;
        
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	mapper_p = (omci_802_1p_map_service_ptr)me_info->attributes;	
    if(mapper_p == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
    }
	ioctlData.msgType = me_info->msg_type;
        
	mapperData.instID	= me_info->inst_id;
	mapperData.tpType  = mapper_p->tpType;
	mapperData.tpPointer  = mapper_p->tpPointer;
	memcpy(mapperData.pbit_GemIWTP, mapper_p->tpPointerP, 8*2);
	memcpy(mapperData.dscp2pbitMap, mapper_p->DSCP2PbitMap, 24);
	mapperData.unmark_frame_opt  = mapper_p->unmarkFrameOpt;
	mapperData.defaultPbit  = mapper_p->defaultPbitAssumption;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
        	
		ioctlData.attrMask = (ME_8021P_MAPPER_ATTR_ALL & (~ME_8021_MAPPER_ATTR_DSCP2PBIT_MAP));
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	return 0;
}

static int omci_flow_handle_evtocd(omci_me_info_ptr me_info)
{
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	if(MT_OMCI_MSG_TYPE_SET    == me_info->msg_type   || 
       MT_OMCI_MSG_TYPE_DELETE == me_info->msg_type   || 
       MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type) 
		return 0;
	else
		return -1;
}

static int omci_flow_handle_gem_iw_tp(omci_me_info_ptr me_info)
{
	meGemIwTp_raw_t gemIwTpData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_GEM_INTERWORK_TP,
		.data = &gemIwTpData
	};
	omci_gem_interwork_tp_ptr gem_iw_tp_p = NULL;
		
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	gem_iw_tp_p = (omci_gem_interwork_tp_ptr)me_info->attributes;	
	if(gem_iw_tp_p == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	ioctlData.msgType = me_info->msg_type;
	ioctlData.instId = me_info->inst_id;

	gemIwTpData.instID  = me_info->inst_id;
	gemIwTpData.gemCTPInstID  = gem_iw_tp_p->gemPortNetCTPConPtr;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_GEM_IWTP_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
    	
 	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
 	}
	return 0;
}

static int omci_flow_handle_gem_ctp(omci_me_info_ptr me_info)
{
	meGemCtp_raw_t gemCtpData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_GEM_PORT_CTP,
		.data = &gemCtpData
	};
	omci_gem_port_ctp_ptr gem_ctp_p = NULL;
		
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}

	ioctlData.instId = me_info->inst_id;
	gem_ctp_p = (omci_gem_port_ctp_ptr)me_info->attributes;	
	if(gem_ctp_p == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	ioctlData.msgType = me_info->msg_type;

	gemCtpData.instID  = me_info->inst_id;
	gemCtpData.portID  = gem_ctp_p->portId;
	gemCtpData.tcontID	= gem_ctp_p->tcontPointer;
	gemCtpData.direction  = gem_ctp_p->direction;
	gemCtpData.trafficMgrPtrUp  = gem_ctp_p->TrafficManagePointerUp;
	gemCtpData.TDProPtrUp= gem_ctp_p->TrafficDescriptorPointerUp;
	gemCtpData.TDProPtrDown= gem_ctp_p->TrafficDescriptorPointerDown;
	
	if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_GEM_CTP_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	return 0;
}


static int omci_flow_handle_veip(omci_me_info_ptr me_info)
{  
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}

    if(MT_OMCI_MSG_TYPE_SET ==  me_info->msg_type){
        return 0;
    }else{
        return -1; // don't support any other actions
    }
    
    return -1;
}

static int omci_flow_handle_multi_gem_iw_tp(omci_me_info_ptr me_info)
{
	meMultiGemIwTp_raw_t multiGemIwTpData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_MULTICAST_GEM_INTERWORK_TP,
		.data = &multiGemIwTpData
	};
	omci_mc_gem_interwork_tp_ptr multi_gem_iw_tp_p = NULL;
		
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	multi_gem_iw_tp_p = (omci_mc_gem_interwork_tp_ptr)me_info->attributes;	
	if(multi_gem_iw_tp_p == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	ioctlData.msgType = me_info->msg_type;

	multiGemIwTpData.instID  = me_info->inst_id;
	multiGemIwTpData.GemCTPInstID  = multi_gem_iw_tp_p->gemPortNetCTPConPtr;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_GEM_IWTP_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
    	
 	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
 	}
	return 0;
}

static int omci_flow_handle_tcont(omci_me_info_ptr me_info)
{
	meTcont_raw_t tcontData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_T_CONT,
		.data = &tcontData
	};
	omci_t_cont_ptr tcont_p = NULL;
		
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	tcont_p = (omci_t_cont_ptr)me_info->attributes;	
	if(tcont_p == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	ioctlData.msgType = me_info->msg_type;

	tcontData.instID  = me_info->inst_id;
	tcontData.allocID = tcont_p->allocId;
	tcontData.policy = tcont_p->policy;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_T_CONT_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
    	
 	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
 	}
	return 0;
}

static int omci_flow_handle_ts(omci_me_info_ptr me_info)
{
	meTS_raw_t tsData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_TRAFFIC_SCHEDULER,
		.data = &tsData
	};
	omci_traffic_scheduler_ptr ts_p = NULL;
		
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	ts_p = (omci_traffic_scheduler_ptr)me_info->attributes;	
	if(ts_p == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	ioctlData.msgType = me_info->msg_type;

	tsData.instID  = me_info->inst_id;
	tsData.tcontPointer = ts_p->tcontPointer;
	tsData.tsPointer = ts_p->trafficSchedulerPointer;
	tsData.policy = ts_p->policy;
	tsData.weight = ts_p->priorityOrWeight;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_TS_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
 	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
 	}
	return 0;
}

static int omci_flow_handle_td(omci_me_info_ptr me_info)
{
	meTD_raw_t tdData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_TRAFFIC_DESCRIPTOR,
		.data = &tdData
	};
	omci_traffic_descriptor_ptr td_p = NULL;
		
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	td_p = (omci_traffic_descriptor_ptr)me_info->attributes;	
	if(td_p == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	ioctlData.msgType = me_info->msg_type;


	tdData.instID  = me_info->inst_id;
	tdData.cir = td_p->cir;
	tdData.pir = td_p->pir;
	tdData.cbs = td_p->cbs;
	tdData.pbs = td_p->pbs;
	tdData.colourMode = td_p->colourMode;
	tdData.ingressColourMode = td_p->ingressColourMode;
	tdData.egressColourMode = td_p->egressColourMode;
	tdData.meterType = td_p->meterType;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_TD_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
 	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
 	}
	return 0;
}

static int omci_flow_handle_pri_queue(omci_me_info_ptr me_info)
{
	mePriorityQ_raw_t priQData = {0};
	FlowRawData_t ioctlData = {
		.classId = OMCI_CLASS_ID_PRIORITY_QUEUE,
		.data = &priQData
	};
	omci_priority_queue_ptr pri_queue_p = NULL;
		
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	ioctlData.instId = me_info->inst_id;
	pri_queue_p = (omci_priority_queue_ptr)me_info->attributes;	
	if(pri_queue_p == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
	}
	ioctlData.msgType = me_info->msg_type;

	priQData.instID  = me_info->inst_id;
	priQData.relatedPort = pri_queue_p->relatedPort;
	priQData.tsPointer = pri_queue_p->trafficSchedulerPointer;
	priQData.weight = pri_queue_p->weight;

    if(MT_OMCI_MSG_TYPE_CREAT  == me_info->msg_type){
		ioctlData.attrMask = ME_PRI_Q_ATTR_ALL;
	}else if(MT_OMCI_MSG_TYPE_SET == me_info->msg_type){
		ioctlData.attrMask = me_info->mask;
        if ( 0 == ioctlData.attrMask ) {
			return 0;
        }
	}else if(MT_OMCI_MSG_TYPE_DELETE != me_info->msg_type){
		return -1;
	}
 	if(0 != gpon_flow_ioctl_import_me_data(&ioctlData)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] gpon_flow_ioctl_import_me_data fail\n",__FUNCTION__,__LINE__);
		return -1;
 	}
	return 0;
}



/**
 * ret val: on success return 0
            on failure return -1
 */
int omci_flow_me_handle(omci_me_info_ptr me_info)
{
	gpon_flow_me_t * me_entry = NULL;
	int ret=0;

	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter [%s][%d] \n", __FUNCTION__, __LINE__);
	if(NULL == me_info){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Parameter is Null.\n",__FUNCTION__,__LINE__);
		return -1;
	}

	me_entry = omci_flow_get_me_by_classid(me_info->class_id);
	if(me_entry == NULL)
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%s][%d]the classId(%d) can not get the entry.\n",__FUNCTION__,__LINE__, me_info->class_id);
		return 0;
	}

	if(me_entry->func != NULL )
	{
		if(me_info->msg_type== MT_OMCI_MSG_TYPE_DELETE){
			ret = omci_attr_get_old_data_except_table_attr(me_info);
			if(ret != 0)
			{
		        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]get data failed.\n",__FUNCTION__,__LINE__);
		        return -1;
		    }  			
		}	
		return me_entry->func(me_info);
	}

	return -1;
}


int omci_flow_cfg_gpon_flow(void)
{
	FlowCfgData_t cfg_data;

	memset(&cfg_data, 0, sizeof(FlowCfgData_t));

    cfg_data.pq_data.instID = T_CONT_INST_START_ID;
    cfg_data.pq_data.relatedPort = T_CONT_INST_START_ID << 16;
	cfg_data.pq_data.weight = 1;
	cfg_data.pq_data.tsPointer = 0;
	
	cfg_data.tcont_data.policy = 1;

	cfg_data.max_eth_num = NUM_OF_QUEUE_PER_UIN_PORT;
	cfg_data.max_tcont_num = NUM_OF_QUEUE_PER_TCONT;
	cfg_data.eth_slot = SLOT_BASE_ID;
	cfg_data.tcont_slot = T_CONT_INST_START_ID;

	cfg_data.trafficMgrOp = pOnuCap->tmOption;

	return gpon_flow_ioctl_cfg_data(&cfg_data);
}

int omci_flow_clean_all_rule(void)
{
	return gpon_flow_ioctl_clean_all();
}


